package com.xneure.code.msg;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.stereotype.Component;
import com.xneure.utils.ObjectUtil;

@SuppressWarnings("rawtypes")
@Component
public class MsgManage{
	private static MsgManage sysMsg = new MsgManage();
	private Map<Class,MessageListenerEntry> msgs;
	public static MsgManage getMsgManage(){
		return new MsgManage();
	}

	/**
	 * 公共消息处理器
	 */
	public static MsgManage getSysMsgManage(){
		return sysMsg;
	}

	@SuppressWarnings("unchecked")
	public <T> void registerListen(MessageListener<? super T> msg){
		registerListen((Class<T>)ObjectUtil.getGenericsFirst(msg),msg);
	}

	@SuppressWarnings("unchecked")
	public <T> void registerListen(Class<T> c,MessageListener<? super T> msg){
		if(null == msg){
			return;
		}
		if(this.msgs == null){
			Map<Class,MessageListenerEntry> tmp = new ConcurrentHashMap<Class,MessageListenerEntry>();
			this.msgs = tmp;
		}
		MessageListenerEntry entry = msgs.get(c);
		if(null == entry){
			entry = new MessageListenerEntry<T>(msg);
			msgs.put(c,entry);
		}else{
			entry.addListener(msg);
		}
	}

	public void sendMessage(Object msg){
		sendMessage(msg,null);
	}

	public void asyncMessage(Object msg){
		asyncMessage(msg,null);
	}

	public void asyncMessage(Object msg,Enum<?> action){
		Thread thread = new Thread(new Runnable(){
			@Override
			public void run(){
				sendMessage(msg,action);
			}
		});
		thread.setDaemon(true);
		thread.start();
	}

	@SuppressWarnings("unchecked")
	public void sendMessage(Object msg,Enum<?> action){
		if(null != msg){
			Class<?> peelingCGLIB = null;
			Object srcObj = msg;
			if(msg instanceof Iterable){
				Iterator iterator = ((Iterable)msg).iterator();
				if(iterator.hasNext()){
					Object tmp = iterator.next();
					if(msg instanceof Class<?>){
						msg = tmp;
					}else{
						peelingCGLIB = ObjectUtil.peelingCGLIB(tmp.getClass());
					}
				}else{
					throw new RuntimeException("消息对象不能为空。");
				}
			}else if(msg instanceof Class<?> == false){
				peelingCGLIB = ObjectUtil.peelingCGLIB(msg.getClass());
			}else{
				peelingCGLIB = (Class<?>)msg;
				msg = null;
			}
			if(null != msgs){
				MessageListenerEntry _msg = msgs.get(peelingCGLIB);
				if(null != _msg){
					_msg.handler(msg,action);
				}
			}
			if(this != sysMsg){
				sysMsg.sendMessage(srcObj,action);
			}
		}else{
			throw new RuntimeException("消息对象不能为空。");
		}
	}

	@SuppressWarnings("unchecked")
	public <T> void delListen(MessageListener<? super T> msg){
		delListen((Class<T>)ObjectUtil.getGenericsFirst(msg),msg);
	}

	public <T> void delListen(Class<T> c,MessageListener<? super T> msg){
		if(null == msg){
			return;
		}
		MessageListenerEntry entry = msgs.get(c);
		MessageListenerEntry delMLE = delMLE(null,entry,msg);
		if(null == delMLE){
			if(msgs.containsKey(c)){
				msgs.remove(c);
			}
		}else{
			msgs.put(c,delMLE);
		}
	}

	@SuppressWarnings("unchecked")
	private <T> MessageListenerEntry delMLE(MessageListenerEntry m1,MessageListenerEntry m2,MessageListener<? super T> msg){
		MessageListenerEntry nextEntry = m2.getNextEntry();
		if(m2.getMsgListener() == msg){
			if(null != m1){
				if(null != nextEntry){
					m1.updataListener(nextEntry,nextEntry.getMsgListener());
				}else{
					m1.updataListener(null,m1.getMsgListener());
				}
			}
			return m1;
		}else{
			return delMLE(m2,nextEntry,msg);
		}
	}
}
